# -*- coding:utf-8 -*-
# @Time : 2021/3/14 11:26 上午
# @Author : hyli
# @File : base_page.py
# @Software : PyCharm
import json
from typing import Dict, List

import allure
import yaml
from appium.webdriver.common.mobileby import MobileBy
from selenium.webdriver.remote.webdriver import WebDriver


# from stage6_adv.conftest import root_log
# from stage6_adv.conftest import root_log


class BasePage:
    # 定义弹框黑名单列表
    # resource-id:gu_   // "日程"页面的返回按钮
    _blacklist = [(MobileBy.XPATH, '//*[@resource-id="com.tencent.wework:id/gu_"]')]
    # 定义错误计数器
    _error_num = 0
    # 定义错误数上限
    _error_max = 3
    # 定义传参字典 如{name:xx},将yaml中的${name}替换为xx
    _params = {}

    def __init__(self, driver: WebDriver = None):
        self.driver = driver

    # 获取到元素
    def find(self, by, locator):
        # root_log.info(f'find: by={by}, locator={locator}')
        try:
            ele = self.driver.find_element(by, locator)
            self._error_num = 0
            return ele
        except Exception as e:
            # root_log.info("未找到元素")
            # 遇到异常时进行截图保存, 可指定截图的保存路径，如以下方式，为指定截图保存路径则生成的截图将会放在与测试用例文件同级结构下。 按照下面截屏保存的路径，生成测试报告的路径应为： pytest test_xx.py --alluredir ./result   即与test_xx.py同级
            self.driver.get_screenshot_as_file('../testcase/result/tmp.png')
            allure.attach.file('../testcase/result/tmp.png', attachment_type=allure.attachment_type.PNG)

            # self.driver.get_screenshot_as_file('tmp.png')
            # allure.attach.file('tmp.png', attachment_type=allure.attachment_type.PNG)

            # 记录错误次数
            self._error_num += 1
            if self._error_num >= self._error_max:
                raise e

            # 弹框异常处理
            for black in self._blacklist:
                eles = self.finds(*black)
                if len(eles) > 0:
                    eles[0].click()
                    return self.find(by, locator)
            raise e

    # 获取到元素集合
    def finds(self, by, locator):
        return self.driver.find_elements(by, locator)

    # 获取到元素并进行点击操作
    def find_click(self, by, locator):
        self.find(by, locator).click()

    # 滑动屏幕，获取到指定文本元素并对其进行点击操作
    def swip_click(self, text):
        self.driver.find_element(MobileBy.ANDROID_UIAUTOMATOR,
                                 'new UiScrollable(new UiSelector().'
                                 'scrollable(true).instance(0)).'
                                 'scrollIntoView(new UiSelector().'
                                 f'text("{text}").instance(0));').click()

    # 获取到元素并进行文本输入
    def find_sendkeys(self, by, locator, value):
        return self.find(by, locator).send_keys(value)

    # 关键字数据驱动：通过读取yaml文件中的属性（关键字），对属性进行判断。根据属性对应的属性值（如:find、find_click等）进而执行相应的操作
    def parse_action(self, path, fun_name):
        with open(path, 'r', encoding='utf-8') as f:
            function = yaml.safe_load(f)
            steps: List[Dict] = function[fun_name]
            # json.dumps:序列化，将python对象转化成字符串
            raw = json.dumps(steps)
            for key, value in self._params.items():
                # 将yaml文件中的含有${xx}的替换成真实的值，${xx}为变量
                raw = raw.replace("${" + key + "}", value)
            # json.loads:发序列化，将python字符串转化成python对象
            steps = json.loads(raw)
            for step in steps:
                if step['action'] == "find":
                    self.find(step['by'], step['locator'])
                elif step['action'] == "finds":
                    self.finds(step['by'], step['locator'])
                elif step['action'] == "find_click":
                    self.find_click(step['by'], step['locator'])
                elif step['action'] == "swip_click":
                    print(step['text'])
                    self.swip_click(step['text'])
                elif step['action'] == "find_sendkeys":
                    self.find_sendkeys(step['by'], step['locator'], step['value'])
